package ar.com.framenet.base.util;

import java.io.IOException;
import java.io.InputStream;
import java.io.StringReader;
import java.io.StringWriter;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;

import org.dom4j.DocumentException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

/**
 * XMLUtils
 * 
 * @author sam
 */
public class XMLUtils {
	/**
	 * Obtiene un parametro validado Metodos copy & paste
	 * 
	 * @param path
	 * @return
	 * @throws Exception
	 */
	public static String validatedPropertyOf(Element ele, String name) throws Exception {
		String value = ele.getAttribute(name);
		if (value == null) {
			throw new Exception("Configuracion de Tivoli, " + name + " del elemento: " + ele.getNodeName() + ".");
		}
		return value;
	}

	/**
	 * Obtiene un parametro validado. Metodos copy & paste
	 * 
	 * @param path
	 * @return
	 * @throws Exception
	 */
	public static String validatedValueOf(Element ele, String path) throws Exception {
		String param = ele.getAttribute(path);
		if ("".equals(param)) {
			throw new Exception("XMLUtils.validatedValueOf, " + path + " es vacio o nulo.");
		}
		return param;
	}

	/**
	 * @param filePath
	 * @return Document
	 * @throws DocumentException
	 * @throws IOException
	 * @throws ParserConfigurationException
	 * @throws SAXException
	 */
	public static Document getDocumentFromFile(String filePath) throws IOException, ParserConfigurationException, SAXException {
		DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
		DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
		Document doc = dBuilder.parse(filePath);
		return doc;
	}

	/**
	 * @param Document
	 * @param String
	 * @return String
	 */
	public static String getValueOf(Document doc, String path) {
		XPathFactory xpathFactory = XPathFactory.newInstance();
		XPath xpath = xpathFactory.newXPath();
		//NodeList links = (NodeList) xpath.evaluate(path, element, XPathConstants.NODESET);
		NodeList links = null;
		try {
			links = (NodeList) xpath.evaluate(path, doc, XPathConstants.NODESET);
		} catch (XPathExpressionException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return links.toString();
	}

	/**
	 * 
	 * @param filePath
	 * @return
	 * @throws DocumentException
	 * @throws IOException
	 * 
	 *             public static Document getDocumentFromInputStream(InputStream
	 *             inputStream) throws DocumentException, IOException { return
	 *             new SAXReader().read(inputStream); }
	 */

	/**
	 * 
	 * @param xmlString
	 * @return Document
	 * @throws ParserConfigurationException
	 * @throws IOException
	 * @throws SAXException
	 * @throws DocumentException
	 */
	public static Document getDocumentFromString(String xmlStream) throws ParserConfigurationException, SAXException, IOException {
		DocumentBuilder db = DocumentBuilderFactory.newInstance().newDocumentBuilder();
		InputSource is = new InputSource();
		is.setCharacterStream(new StringReader(xmlStream));

		Document doc = db.parse(is);

		return doc;
	}

	/**
	 * Obtiene un document desde un InputStream
	 * 
	 * @param xmlStream
	 * @return
	 * @throws ParserConfigurationException
	 * @throws SAXException
	 * @throws IOException
	 */
	public static Document getDocumentFromStream(InputStream xmlStream) throws ParserConfigurationException, SAXException, IOException {
		DocumentBuilder db = DocumentBuilderFactory.newInstance().newDocumentBuilder();
		Document doc = db.parse(xmlStream);
		return doc;
	}

	/**
	 * Obtiene una String
	 * 
	 * @param dom
	 * @return
	 * @throws IOException
	 * 
	 *             public static String
	 *             getDocumentStringWithCompactFormat(Document dom) throws
	 *             IOException { OutputFormat format =
	 *             OutputFormat.createCompactFormat();
	 *             format.setTrimText(false);
	 * 
	 *             ByteArrayOutputStream ostream = new ByteArrayOutputStream();
	 *             XMLWriter writer = new XMLWriter( ostream, format );
	 *             writer.write( dom ); return new
	 *             String(ostream.toByteArray()); }
	 */

	/**
	 * @param Document
	 * @return xmlString
	 * @throws TransformerException
	 */
	public static String getXmlAsString(Document doc) throws TransformerException {
		//set up a transformer
		TransformerFactory transFactory = TransformerFactory.newInstance();
		Transformer trans = transFactory.newTransformer();
		trans.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
		trans.setOutputProperty(OutputKeys.INDENT, "yes");

		//create string from xml tree
		StringWriter sw = new StringWriter();
		StreamResult result = new StreamResult(sw);
		DOMSource source = new DOMSource(doc);
		trans.transform(source, result);
		String xmlString = sw.toString();

		return xmlString;
	}

	public static Document getDocumentFromElement(Element element) {
		Document doc = null;

		try {
			TransformerFactory transformerFactory = TransformerFactory.newInstance();
			Transformer transformer = transformerFactory.newTransformer();
			StreamResult result = new StreamResult(new StringWriter());
			DOMSource source = new DOMSource(element);
			transformer.transform(source, result);
			String xmlString = result.getWriter().toString();
			doc = getDocumentFromString(xmlString);
		} catch (ParserConfigurationException e) {
			e.printStackTrace();
		} catch (SAXException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (TransformerConfigurationException e) {
			e.printStackTrace();
		} catch (TransformerException e) {
			e.printStackTrace();
		}

		return doc;
	}

}
